package org.dromara.demo.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.demo.base.ErrorCode;
import org.dromara.demo.common.XxmjException;

import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * @ClassName: ValidateUtil
 * @Desciption: 参数校验工具类
 * @Author: 2206150164
 * @Date 2024/7/17 上午11:30
 */
public class ValidateUtil {

    /**
     * 验证字符串字段是否为空。
     * <p>
     * 此方法用于检查传入的字段是否为空或仅包含空格。如果字段为空，则抛出一个包含错误代码和错误消息的TomException异常。
     * 错误消息格式为"{fieldName} isBlank"，其中fieldName是字段的名称。
     * 这种验证机制有助于在调用方犯错时提供更清晰的错误信息，以便快速定位和解决问题。
     *
     * @param field     待验证的字符串字段。
     * @param fieldName 字段的名称，用于在错误消息中标识出错的字段。
     * @throws XxmjException 如果字段为空，则抛出此异常，包含错误代码和错误消息。
     */
    public static void validateStringField(String field, String fieldName) {
        if (StrUtil.isBlank(field)) {
            throw new ServiceException(fieldName + " isBlank.");
        }
    }

    /**
     * 验证指定字段是否为非空。此方法用于确保传入的字段对象不为null，
     * 如果字段为null，则抛出一个包含错误代码和错误信息的TomException异常。
     * 这种方式的异常处理有助于调用者明确知道是哪个字段出现了空值问题。
     *
     * @param field     待验证的字段对象。
     * @param fieldName 字段的名称，用于在异常信息中指出具体是哪个字段出现了问题。
     * @throws XxmjException 如果字段为null，则抛出此异常，异常包含错误代码和错误信息。
     */
    public static void validateNonNullField(Object field, String fieldName) {
        if (Objects.isNull(field)) {
            throw new ServiceException(fieldName + " isNull.");
        }
    }

    /**
     * 验证时间范围的合法性。
     * <p>
     * 该方法用于检查指定的开始时间和结束时间是否符合逻辑上的要求，即结束时间必须在开始时间之后。
     * 如果开始时间和结束时间任一为空，或结束时间早于开始时间，则抛出异常。
     * 这种验证对于确保时间相关的业务逻辑的正确性非常重要。
     *
     * @param startTime     开始时间，用于比较结束时间是否在其之后。
     * @param endTime       结束时间，需要大于或等于开始时间。
     * @param startTimeName 开始时间的名称，用于错误消息中标识开始时间。
     * @param endTimeName   结束时间的名称，用于错误消息中标识结束时间。
     * @throws XxmjException 如果结束时间早于开始时间，则抛出此异常，包含错误代码和错误信息。
     */
    public static void validateTimeRange(Date startTime, Date endTime, String startTimeName, String endTimeName) {
        validateNonNullField(startTime, startTimeName);
        validateNonNullField(endTime, endTimeName);
        if (startTime.after(endTime)) {
            throw new ServiceException(endTimeName + " should be after " + startTimeName + ".");
        }
    }

    /**
     * 验证字段是否为非负数。
     * <p>
     * 此方法用于检查给定字段是否为非负数。如果字段为null或大于等于0，则验证通过。
     * 如果字段不为null且小于0，则抛出一个包含错误代码和错误消息的TomException异常。
     * 错误消息中包含字段名，以指示哪个字段的值不符合非负数的要求。
     *
     * @param field     要验证的数字字段。
     * @param fieldName 字段的名称，用于在错误消息中标识出问题的字段。
     * @throws XxmjException 如果字段为非null且小于0，则抛出此异常。
     */
    public static void validateNonNegative(Number field, String fieldName) {
        validateNonNullField(field, fieldName);
        if (field.doubleValue() < 0.0) {
            throw new ServiceException(fieldName + " should be non-negative.");
        }
    }

    /**
     * 验证布尔值类型的整数是否为负或非法值
     * 此方法旨在确保表示布尔值的整数字段仅限于0或1，以符合预期的参数范围
     *
     * @param field     要验证的整数字段，应为布尔值的数字表示
     * @param fieldName 字段的名称，用于错误消息中
     * @throws XxmjException 如果字段值不是0或1，则抛出异常，指示参数错误
     */
    public static void validateBooleanIntegerNegative(Integer field, String fieldName) {
        validateNonNegative(field, fieldName);
        if (field < 0 || field > 1) {
            throw new ServiceException(fieldName + " should between 0 and 1.");
        }
    }

    /**
     * 验证集合对象不为空。
     * 该方法用于检查传入的集合对象是否为空，如果为空，则抛出一个包含错误代码和错误信息的TomException异常。
     * 这里的目的是确保调用者传入的集合对象是有效的，避免因为空集合而导致的后续处理逻辑出错。
     *
     * @param objects   需要验证的集合对象，可以是任何类型的集合。
     * @param fieldName 集合对象对应的字段名，用于生成错误信息。
     * @throws XxmjException 如果集合对象为空，则抛出此异常，异常包含错误代码和错误信息。
     */
    public static void validateCollEmpty(Collection<?> objects, String fieldName) {
        if (CollUtil.isEmpty(objects)) {
            throw new ServiceException(fieldName + " is empty.");
        }
    }

    /**
     * 验证Map对象不为空。
     * 该方法用于检查传入的Map对象是否为空，如果为空，则抛出一个包含错误代码和错误信息的TomException异常。
     * 这里的目的是确保调用者传入的Map对象是有效的，避免因为空Map而导致的后续处理逻辑出错。
     *
     * @param map       需要验证的Map对象。
     * @param fieldName Map对象对应的字段名，用于生成错误信息。
     * @throws XxmjException 如果Map对象为空，则抛出此异常，异常包含错误代码和错误信息。
     */
    public static void validateMapEmpty(Map<?, ?> map, String fieldName) {
        if (MapUtil.isEmpty(map)) {
            throw new ServiceException( fieldName + " is empty.");
        }
    }


}
